home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
090
/
cmln0586.arc
/
CLIPPER.LTG
< prev
next >
Wrap
Text File
|
1986-04-06
|
6KB
|
172 lines
/* Line and Polygon Clip Routine - Clipper */
/* */
/* This routine is a clipping routine designed to clip lines */
/* or polygons. Parameters are as follows: */
/* */
/* points - Object points to be clipped. */
/* num_points - Number of points in object. */
/* polygon - Polygon flag (polygon = 1, line = 0). */
/* color - Color of object. */
/* */
struct DTABLE { /* declare structure for data table */
int x; /* data table x value */
int y; /* data table y value */
};
#define max( A, B ) ((A) > (B) ? (A) : (B)) /* define a MAX function */
#define min( A, B ) ((A) < (B) ? (A) : (B)) /* define a MIN function */
Clipper( points, num_points, polygon, color )
struct DTABLE *points;
int num_points;
int polygon;
int color;
{
char Outcodes();
char outcode1, outcode2, code;
int done, i, total = 0;
struct DTABLE *pt1, *pt2, *out; /* coordinate pointers */
struct DTABLE curpt, corner[4]; /* last point; corners of window */
out = (struct DTABLE *)calloc( num_points+8, sizeof(struct DTABLE));
corner[0].x = XMIN; corner[0].y = YMIN;
corner[1].x = XMAX; corner[1].y = YMIN;
corner[2].x = XMIN; corner[2].y = YMAX;
corner[3].x = XMAX; corner[3].y = YMAX;
pt1 = points;
for ( i = 1; i<num_points; ++i ) {
done = 0;
pt2 = points+i;
curpt.x = pt2->x; curpt.y = pt2->y; /* SAVE CURRENT POINT */
do {
outcode1 = Outcodes( pt1 );
outcode2 = Outcodes( pt2 );
if (outcode1 & outcode2) { /* REJECT POINTS */
if (polygon) {
code = Save_Corner(pt1, outcode1);
if (code) total = Put_Point( &corner[code/3-1], out, total );
} else {
if (total > 1) polyline( color, out, total);
total = 0;
};
done = 1;
}
else if ((!outcode1) && (!outcode2)) { /* ACCEPT POINTS */
total = Put_Point( pt1, out, total );
total = Put_Point( pt2, out, total );
done = 1;
}
else if (!outcode1) { /* point 1 inside; point 2 outside */
Clip( pt2, pt1, outcode2 );
}
else if (!outcode2) { /* point 2 inside; point 1 outside */
if (polygon) {
code = Save_Corner(pt1, outcode1);
if (code) total = Put_Point( &corner[code/3-1], out, total );
} else {
if (total > 1) polyline( color, out, total);
total = 0;
};
Clip( pt1, pt2, outcode1 );
}
else { /* both points outside; different sides */
if (polygon) {
code = Save_Corner(pt1, outcode1);
if (code) total = Put_Point( &corner[code/3-1], out, total );
} else {
if (total > 1) polyline( color, out, total);
total = 0;
};
Clip( pt1, pt2, outcode1 );
}
} while (!done);
pt1->x = curpt.x; pt1->y = curpt.y;
} /* end for loop */
if (polygon) { /* first point must equal last */
if((out[0].x != out[total].x) && (out[0].y != out[total].y))
total = Put_Point( &out[0], out, total );
polyhatch( color, out, total );
} else if (total > 1) polyline( color, out, total);
free(out);
}
int Clip( pt1, pt2, code )
struct DTABLE *pt1, *pt2;
char code;
{
if (code & 0x08) { /* CLIP TOP */
pt1->x += (pt2->x-pt1->x) * (YMAX-pt1->y) / (pt2->y-pt1->y);
pt1->y = YMAX;
} else if (code & 0x02) { /* CLIP BOTTOM */
pt1->x += (pt2->x-pt1->x) * (YMIN-pt1->y) / (pt2->y-pt1->y);
pt1->y = YMIN;
} else if (code & 0x04) { /* CLIP RIGHT */
pt1->y += (pt2->y-pt1->y) * (XMAX-pt1->x) / (pt2->x-pt1->x);
pt1->x = XMAX;
} else if (code & 0x01) { /* CLIP LEFT */
pt1->y += (pt2->y-pt1->y) * (XMIN-pt1->x) / (pt2->x-pt1->x);
pt1->x = XMIN;
};
}
char Outcodes( pt )
struct DTABLE *pt;
{
char code = 0x00;
if (pt->x < XMIN) code |= 0x01; /* Left Side */
if (pt->x > XMAX) code |= 0x04; /* Right Side */
if (pt->y < YMIN) code |= 0x02; /* Bottom Side */
if (pt->y > YMAX) code |= 0x08; /* Top Side */
return ( code );
}
int Save_Corner( pt, code )
struct DTABLE *pt;
char code;
{
if (pt->x == XMIN) return(code|0x01); /* Bottom Boundary */
if (pt->x == XMAX) return(code|0x04); /* Top Boundary */
if (pt->y == YMIN) return(code|0x02); /* Left Boundary */
if (pt->y == YMAX) return(code|0x08); /* Right Boundary */
if (!(code%3)) return(code); /* Point is in corner */
return(0); /* Don't save corner */
}
int Put_Point( pt, out, num )
struct DTABLE *pt, *out;
int num;
{
float m1,m2; /* slopes of two pairs of points */
float dx1,dx2; /* delta x of two pairs of points */
if (!num) { /* FIRST POINT TO BE ENTERED */
out[num].x = pt->x; out[num].y = pt->y; return( num+1 );
}
if (num) /* NEW POINT = LAST POINT? */
if ((pt->x == out[num-1].x) && (pt->y == out[num-1].y)) return(num);
if (num == 1) { /* NO COLINEAR POINTS YET */
out[num].x = pt->x; out[num].y = pt->y; return( num+1 );
}
dx1 = (float)(out[num-1].x - out[num-2].x);
dx2 = (float)(pt->x - out[num-2].x);
if ((dx1 == 0.0) && ( dx2 == 0.0)) { /* VERTICAL SLOPES */
out[num-1].x = pt->x; out[num-1].y = pt->y; return(num);
}
if ((int)dx1 && (int)dx2) {
m1 = (float)(out[num-1].y - out[num-2].y) / dx1;
m2 = (float)(pt->y - out[num-2].y) / dx2;
if ( m1 == m2 ) { /* REMOVE COLINEAR POINTS */
out[num-1].x = pt->x; out[num-1].y = pt->y; return(num);
}
}
out[num].x = pt->x; out[num].y = pt->y; return( num+1 );
}